﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ServiceModel.Activation;
using System.ServiceModel;
using System.IO;
using System.ServiceModel.Web;
using System.Net;
using System.Security;
using COFE.Core.Lister;
using COFE.IO;
using COFE.Core;
using COFE.Data;
using COFE.Core.EntryType;
using System.Text.RegularExpressions;
using COFE.Core.Utils;
using COFE.Core.Entry;

namespace COFE.Web.Services
{
    /// <summary>
    /// Services that enables accessing an entry, it's properties, metadata and resources.
    /// </summary>
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class EntryServices : IEntryServices
    {
        #region Constructor

        public EntryServices()
        {

        }

        #endregion

        #region Methods

        public Stream GetEntry(string entryID, string json)
        {
            return ServicesUtils.ExecuteAndReturn<string, Stream>(
                (eID) =>
                {
                    Entry entry = ServiceConstants.Profile.LookupEntry(new Guid(eID));
                    return EncodeObjectUtils.EncodeObject(entry, json);
                }, entryID);
        }

        public Stream GetEntry2(string entryID, string json) { return GetEntry(entryID, json); }

        public Stream ListDirectory(string entryID, string refresh, string json, string page)
        {

            ServicesUtils.Execute<string>(
             (eID) =>
             {
                 var entry = ServiceConstants.Profile.LookupEntry(new Guid(eID));
                 if (refresh == "true")
                     entry.Refresh();
                 
                 string ss = string.Format("root={0}&subdir=false",  ServicesUtils.UrlPathToCOFEPath(entry.Path));
                 string desturi = ServiceConstants.Templates.FormatTemplate(
                     ServiceConstants.Templates.BaseSearch,
                       new Dictionary<string, string>() { { "#ss#", ss } });

                 ServicesUtils.SetRedirect(desturi, true, "path");
             }, entryID);

            return null;


            //return ServicesUtils.ExecuteAndReturn<string, Entry, Stream>(
            // (eID) => { return ServiceConstants.Profile.LookupEntry(new Guid(eID)); },
            // (entry) =>
            // {
            //     if (refresh == "true")
            //         entry.Refresh();
            //     string pageFilter = String.IsNullOrEmpty(page) ? "" :
            //         "page:" + Regex.Replace(page, "[^\\d\\.]", "");
            //     EntryList result = ServiceConstants.Profile.ListEntry(entry, pageFilter);                 
            //     return EncodeObjectUtils.EncodeObject(result, json);
            // },
            // (entry) =>
            // {
            //     return entry.GetProperty(DatabaseProperties.LastListTime)
            //         .ValueAsUtcDateTime;
            // }
            //, entryID);
        }

        public Stream GetMetadata(string entryID, string json)
        {
            return ServicesUtils.ExecuteAndReturn<string, Entry, Stream>(
             (eID) => { return ServiceConstants.Profile.LookupEntry(new Guid(eID)); },
             (entry, eId) =>
             {
                 return EncodeObjectUtils.EncodeObject(entry.Metadata, json);
             },
             (entry, eId) =>
             {
                 return entry.GetProperty(DatabaseProperties.PropertyRefreshTime)
                     .ValueAsUtcDateTime;
             }
            , entryID);
        }        

        public void GetEntryType(string entryID, string rel)
        {
            ServicesUtils.Execute((eID) =>
                {
                    Entry entry = ServiceConstants.Profile.LookupEntry(new Guid(eID));

                    var entryTypeInfo =
                        new EntryType(COFEShared
                            .EntryTypeDictionary[entry.EntryTypeID]);
                    string desturi;

                    if (rel != null)
                    {
                        desturi = entryTypeInfo.FindLink(rel).Uri;                        
                    }
                    else
                        desturi = entryTypeInfo.CreateLink(new LinkTemplate(MediaType.Unknown, RelationType.Self,
                            ServiceConstants.Templates.EntryType)).Uri;

                    ServicesUtils.SetRedirect(desturi, true);
                }, entryID);
        }        

        public Stream GetResource(string entryID, string resource, string rel, string json)
        {
            return ServicesUtils.ExecuteAndReturn<string, string, Entry, Stream>(
             (eID, res) => ServiceConstants.Profile.LookupEntry(new Guid(eID)),
             (entry, eID, res) =>
             {                 
                 PropertyPair ppResource = ServiceConstants.Profile.GetResource(entry, res);
                 if (ppResource.Type == typeof(IResourceList))
                 {
                     var rlist = new ResourceList(new Guid(eID), ppResource.Value as IResourceList);
                     if (rel != null)
                     {                         
                         ServicesUtils.SetRedirect(rlist.FindLink(rel).Uri, true);
                         return null;
                     }
                     else
                     {                         
                         return EncodeObjectUtils.EncodeObject(rlist, json);
                     }
                 }

                 MediaType mediaType;
                 Stream retVal = ppResource.ToMemoryStream(out mediaType);

                 string resourceExt = MediaTypeExtension.ToDefaultExtension(mediaType);
                 if (resource != null)
                     ServicesUtils.SetContentHeaderAsFile(resource + resourceExt);
                 WebOperationContext.Current.OutgoingResponse.ContentType = MediaTypeExtension.ToMIME(mediaType);

                 return retVal;
             },
             
             (entry, eId, res) =>
             {
                 return entry.GetProperty(DatabaseProperties.PropertyRefreshTime)
                     .ValueAsUtcDateTime;
             }, entryID, resource);
        }

        public Stream GetFileStream(string entryID)
        {
            return ServicesUtils.ExecuteAndReturn<string, Stream>(
            (eID) =>
            {
                Entry entry = ServiceConstants.Profile.LookupEntry(new Guid(eID));
                Stream stream = ServiceConstants.Profile.GetFileStream(entry);
                ServicesUtils.SetContentHeaderAsFile(entry.Name);
                return stream;
            }, entryID);
        }

        public void SetFileStream(string entryID, Stream fileContents)
        {
            ServicesUtils.Execute<string, Stream>(
             (eID, stream) =>
             {
                 Entry entry = ServiceConstants.Profile.LookupEntry(new Guid(eID));
                 ServiceConstants.Profile.SetFileStream(entry, stream);
             }, entryID, fileContents);
        }

        #endregion

        #region Data


        #endregion

        #region Public Properties


        #endregion


        //public void RefreshEntry(string entryID)
        //{
        //    contentServices.RefreshEntry(entryID);
        //}

        //public void UpdateEntry(string entryID, Stream entryStream)
        //{
        //    Entry search = Entry.EntryFromXmlStream(entryStream);
        //    contentServices.UpdateEntry(entryID, search);
        //}

        //public void DeleteEntry(string entryID)
        //{
        //    contentServices.DeleteEntry(entryID);
        //}






    }
}